package io.gitee.shengzheng1999.esbcommon.common.utils;

import java.lang.reflect.Field;
import java.time.LocalDate;
import java.time.LocalDateTime;
import java.time.LocalTime;
import java.time.format.DateTimeFormatter;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import io.gitee.shengzheng1999.esbcommon.exception.BaseException;
import io.gitee.shengzheng1999.esbcommon.exception.ExceptionCodes;
import io.gitee.shengzheng1999.esbcommon.vo.ParamField;

/**
 * @className		: ReflectUtil
 * @description	: 
 * @summary		:
 * @history		:
 * ------------------------------------------------------------------------------
 * date			version		modifier		remarks                   
 * ------------------------------------------------------------------------------
 * 2023/03/10	1.0.0		sheng.zheng		初版
 *
 */
public class ReflectUtil {
	/**
	 * 
	 * @methodName		: getValue
	 * @description	: 从对象item中获取指定属性的值
	 * @param item		: 对象
	 * @param propName	: 属性名
	 * @return			: 属性值
	 * @history		:
	 * ------------------------------------------------------------------------------
	 * date			version		modifier		remarks                   
	 * ------------------------------------------------------------------------------
	 * 2022/01/23	1.0.0		sheng.zheng		初版
	 *
	 */
	public static Object getValue(Object item,String propName) {
		Object retValue = null;
    	try {
    		Class<?> clazz = (java.lang.Class<?>) item.getClass();
    		Field field = clazz.getDeclaredField(propName);
    		field.setAccessible(true);
    		retValue = field.get(item);
    	}catch (NoSuchFieldException e) {
    		LogUtil.error(e);
    		throw new BaseException(ExceptionCodes.ERROR,e.getMessage());
    	}catch (IllegalAccessException e) {
    		LogUtil.error(e);
    		throw new BaseException(ExceptionCodes.ERROR,e.getMessage());
    	}catch(Exception e) {
    		LogUtil.error(e);
    		throw new BaseException(ExceptionCodes.ERROR,e.getMessage());
    	}
    	return retValue;		
	}
	
	/**
	 * 
	 * @methodName		: setValue
	 * @description	: 设置对象值
	 * @param item		: 对象类
	 * @param propName	: 属性名
	 * @param oValue	: 需要设置的属性值
	 * @history		:
	 * ------------------------------------------------------------------------------
	 * date			version		modifier		remarks                   
	 * ------------------------------------------------------------------------------
	 * 2022/01/23	1.0.0		sheng.zheng		初版
	 *
	 */
	public static void setValue(Object item,String propName,Object oValue){
    	try {
    		Class<?> clazz = (java.lang.Class<?>) item.getClass();
    		Field field = clazz.getDeclaredField(propName);
    		field.setAccessible(true);
    		field.set(item,oValue);
    	}catch (NoSuchFieldException e) {
    		LogUtil.error(e);
    		throw new BaseException(ExceptionCodes.ERROR,e.getMessage());
    	}catch (IllegalAccessException e) {
    		LogUtil.error(e);
    		throw new BaseException(ExceptionCodes.ERROR,e.getMessage());
    	}catch(Exception e) {
    		LogUtil.error(e);
    		throw new BaseException(ExceptionCodes.ERROR,e.getMessage());
    	}		
	}	
	
    /**
     * 
     * @methodName		: getSubFieldList
     * @description	: 抽取T类型的列表中指定字段的列表
     * @param inputList	: 输入列表
     * @param fieldName	: 字段名称
     * @return			: 指定字段的列表
     * @history		:
     * ------------------------------------------------------------------------------
     * date			version		modifier		remarks                   
     * ------------------------------------------------------------------------------
     * 2021/01/01	1.0.0		sheng.zheng		初版
     *
     */
	public static List<Object> getSubFieldList(List<?> inputList,String fieldName){
    	List<Object> retList = new ArrayList<Object>();
    	// 遍历新列表
    	for(int i = 0; i < inputList.size(); i++) {
    		Object item = inputList.get(i);
    		try {
        		// 取得新对象的当前字段值
    			Class<?> newClazz = (Class<?>) item.getClass();        		
        		Field newField = newClazz.getDeclaredField(fieldName);
        		newField.setAccessible(true);
        		Object newValue = newField.get(item); 
        		// 加入列表中
        		retList.add(newValue);
        		
    		}catch (NoSuchFieldException e) {
        		LogUtil.error(e);
        		throw new BaseException(ExceptionCodes.ERROR,e.getMessage());
        	}catch (IllegalAccessException e) {
        		LogUtil.error(e);
        		throw new BaseException(ExceptionCodes.ERROR,e.getMessage());
        	}catch(Exception e) {
        		LogUtil.error(e);
        		throw new BaseException(ExceptionCodes.ERROR,e.getMessage());
        	}    		
    	}
    	return retList;
    }	
	
	/**
	 * 
	 * @methodName		: getShortTypeName
	 * @description	: 获取短类型名
	 * @param type		: 类型名，可以为String或java.lang.String形式
	 * @return			: 短类型名
	 * @history		:
	 * ------------------------------------------------------------------------------
	 * date			version		modifier		remarks                   
	 * ------------------------------------------------------------------------------
	 * 2022/01/23	1.0.0		sheng.zheng		初版
	 *
	 */
	public static String getShortTypeName(String type) {
		String shortType = "";
		// 类似java.lang.String形式
		String[] splits = type.split("\\.");
		if (splits.length > 0) {
			// 取最后一个元素
			shortType = splits[splits.length - 1];
		}
		return shortType;
	}	
	
    /**
     * 
     * @methodName		: getValuesMap
     * @description	: 根据给定的字段名列表，从对象中获取对应字段的值的字典
     * @param <T>		: 泛型类型
     * @param item		: 泛型对象
     * @param fieldNameList: 字段名列表
     * @return			: Map<String,Object>类型，key为字段名，value为字段对应的值
     * @history		:
     * ------------------------------------------------------------------------------
     * date			version		modifier		remarks                   
     * ------------------------------------------------------------------------------
     * 2021/01/01	1.0.0		sheng.zheng		初版
     *
     */
	public static <T> Map<String,Object> getValuesMap(T item,List<String> fieldNameList){
		Map<String,Object> map = new HashMap<String,Object>();
		@SuppressWarnings("unchecked")
		Class<T> newClazz = (Class<T>) item.getClass();
		Object oValue = null;
		for (String fieldName : fieldNameList) {
			try {
        		Field field = newClazz.getDeclaredField(fieldName);
        		field.setAccessible(true);
        		oValue = field.get(item);     		
        		map.put(fieldName, oValue);
    		}catch (NoSuchFieldException e) {
        		continue;
        	}catch (IllegalAccessException e) {
        		LogUtil.error(e);
        		throw new BaseException(ExceptionCodes.ERROR,e.getMessage());
        	}catch(Exception e) {
        		LogUtil.error(e);
        		throw new BaseException(ExceptionCodes.ERROR,e.getMessage());
        	} 			
		} 
		return map;
	}
	
    /**
     * 
     * @methodName		: getValuesMap
     * @description	: 根据给定的字段名数组，从对象中获取对应字段的值的字典
     * @param <T>		: 泛型类型
     * @param item		: 泛型对象
     * @param fieldNames: 字段名数组
     * @return			: Map<String,Object>类型，key为字段名，value为字段对应的值
     * @history		:
     * ------------------------------------------------------------------------------
     * date			version		modifier		remarks                   
     * ------------------------------------------------------------------------------
     * 2024/01/23	1.0.0		sheng.zheng		初版
     *
     */
	public static <T> Map<String,Object> getValuesMap(T item,String[] fieldNames){
		Map<String,Object> map = new HashMap<String,Object>();
		@SuppressWarnings("unchecked")
		Class<T> newClazz = (Class<T>) item.getClass();
		Object oValue = null;
		for (String fieldName : fieldNames) {
			try {
	    		Field field = newClazz.getDeclaredField(fieldName);
	    		field.setAccessible(true);
	    		oValue = field.get(item);     		
	    		map.put(fieldName, oValue);
			}catch (NoSuchFieldException e) {
	    		continue;
	    	}catch (IllegalAccessException e) {
	    		LogUtil.error(e);
	    		throw new BaseException(ExceptionCodes.ERROR,e.getMessage());
	    	}catch(Exception e) {
	    		LogUtil.error(e);
	    		throw new BaseException(ExceptionCodes.ERROR,e.getMessage());
	    	} 			
		} 
		return map;
	}	
	
	/**
	 * 
	 * @methodName		: setValues
	 * @description	: 根据参数字典设置对象列表的属性值
	 * @param <T>		: 泛型类型，实体对象类
	 * @param itemList	: 对象列表
	 * @param params	: 参数字典
	 * @history		:
	 * ------------------------------------------------------------------------------
	 * date			version		modifier		remarks                   
	 * ------------------------------------------------------------------------------
	 * 2024/01/23	1.0.0		sheng.zheng		初版
	 *
	 */
	public <T> void setValues(List<T> itemList,Map<String,Object> params) {
		for(T item : itemList) {
			for(String key : params.keySet()) {
				Object oVal = params.get(key);
				try {
					setValue(item, key, oVal);
				}catch(Exception e) {
					// 非属性字段，忽略
					continue;
				}
			}
		}
	}	
	
	/**
	 * 
	 * @methodName		: getValueFiledNames
	 * @description	: 比较同类型的两个对象，取得值有不同的字段名列表
	 * @param <T>		: 泛型类型
	 * @param item		: 源对象
	 * @param destItem	: 目标对象
	 * @return			: 属性值不同的字段名列表
	 * @history		:
	 * ------------------------------------------------------------------------------
	 * date			version		modifier		remarks                   
	 * ------------------------------------------------------------------------------
	 * 2023/03/24	1.0.0		sheng.zheng		初版
	 *
	 */
	public static <T> List<String> getValueFiledNames(T item, T destItem) {
		List<String> fieldNameList = new ArrayList<String>();
		// 获取对象item的运行时的类
		Class<?> clazz = (Class<?>) item.getClass();
		// 获取属性字段数组
		Field[] fields = clazz.getDeclaredFields();
		// 遍历所有属性字段
		for (int i = 0; i < fields.length; i++) {
			Field field = fields[i];
			String fieldName = field.getName();
			try {
				// 将私有属性改为可访问
				field.setAccessible(true);
				Object oVal = field.get(item);
				Object oVal2 = field.get(destItem);
				if (oVal != null) {
					if (oVal2 != null) {
						if (!oVal.equals(oVal2)) {
							fieldNameList.add(fieldName);
						}
					}else {
						fieldNameList.add(fieldName);
					}
				}else {
					if (oVal2 != null) {
						fieldNameList.add(fieldName);
					}
				}				
			}catch (IllegalAccessException e) {
	    		LogUtil.error(e);
	    		continue;
	    	}catch(Exception e) {
	    		LogUtil.error(e);
	    		continue;
	    	}
		}
		return fieldNameList;
	}	
	
	/**
	 * 
	 * @methodName		: hasSameSubPropValues
	 * @description	: 比较同类型的两个对象，在给定属性名列表中，是否属性值都相同
	 * @param <T>		: 泛型类型
	 * @param item		: 源对象
	 * @param destItem	: 目标对象
	 * @param fieldNameList: 属性名列表
	 * @return			: 属性值都相同返回ture，否则返回false
	 * @history		:
	 * ------------------------------------------------------------------------------
	 * date			version		modifier		remarks                   
	 * ------------------------------------------------------------------------------
	 * 2023/03/25	1.0.0		sheng.zheng		初版
	 *
	 */
	public static <T> boolean hasSameSubPropValues(T item, T destItem,
			List<String> fieldNameList) {
		boolean bRet = true;
		@SuppressWarnings("unchecked")
		Class<T> newClazz = (Class<T>) item.getClass();
		for (String fieldName : fieldNameList) {
			try {
				Field field = newClazz.getDeclaredField(fieldName);
				field.setAccessible(true);
				Object oVal = field.get(item);
				Object oVal2 = field.get(destItem);
				if (oVal != null) {
					if (oVal2 != null) {
						if (!oVal.equals(oVal2)) {
							bRet = false;
							break;
						}
					}else {
						bRet = false;
						break;						
					}
				}else {
					if (oVal2 != null) {
						bRet = false;
						break;						
					}
				}
			}catch (NoSuchFieldException e) {
	    		continue;
	    	}catch (IllegalAccessException e) {
	    		LogUtil.error(e);
	    		throw new BaseException(ExceptionCodes.ERROR,e.getMessage());
	    	} catch (Exception e) {
	    		LogUtil.error(e);
	    		throw new BaseException(ExceptionCodes.ERROR,e.getMessage());
	    	}
		}			
		  
				
		return bRet;
	}
	
	/**
	 * 
	 * @methodName		: hasSameSubPropValues
	 * @description	: 比较同类型的两个对象，在给定属性名数组中，是否属性值都相同
	 * @param <T>		: 泛型类型
	 * @param item		: 源对象
	 * @param destItem	: 目标对象
	 * @param fieldNames: 属性名数组
	 * @return			: 属性值都相同返回ture，否则返回false
	 * @history		:
	 * ------------------------------------------------------------------------------
	 * date			version		modifier		remarks                   
	 * ------------------------------------------------------------------------------
	 * 2024/01/23	1.0.0		sheng.zheng		初版
	 *
	 */
	public static <T> boolean hasSameSubPropValues(T item, T destItem,
			String[] fieldNames) {
		boolean bRet = true;
		@SuppressWarnings("unchecked")
		Class<T> newClazz = (Class<T>) item.getClass();
		for (String fieldName : fieldNames) {
			try {
	    		Field field = newClazz.getDeclaredField(fieldName);
	    		field.setAccessible(true);
				Object oVal = field.get(item);
				Object oVal2 = field.get(destItem);
				if (oVal != null) {
					if (oVal2 != null) {
						if (!oVal.equals(oVal2)) {
							bRet = false;
							break;
						}
					}else {
						bRet = false;
						break;						
					}
				}else {
					if (oVal2 != null) {
						bRet = false;
						break;						
					}
				}
			}catch (NoSuchFieldException e) {
	    		continue;
	    	}catch (IllegalAccessException e) {
	    		LogUtil.error(e);
	    		throw new BaseException(ExceptionCodes.ERROR,e.getMessage());
	    	} catch (Exception e) {
	    		LogUtil.error(e);
	    		throw new BaseException(ExceptionCodes.ERROR,e.getMessage());
	    	}  
				
		}			
				
		return bRet;
	}	
	
	/**
	 * 
	 * @methodName		: checkDataType
	 * @description	: 检查参数的数据类型
	 * @param <T>		: 泛型类型
	 * @param params	: 输入参数
	 * @param paramPropMap: 参数属性映射字典
	 * @param item		: 对象实例，一般为新建对象，保留默认值
	 * @history		:
	 * ------------------------------------------------------------------------------
	 * date			version		modifier		remarks                   
	 * ------------------------------------------------------------------------------
	 * 2023/03/25	1.0.0		sheng.zheng		初版
	 *
	 */
	@SuppressWarnings({ "unused", "unchecked" })
	public static <T> void checkDataType(Map<String,Object> params,
			Map<String,ParamField> paramPropMap,T item) {
		ParamField pfItem = null;
		Class<?> clazz = (Class<?>) item.getClass();
		String type = "";
		String shortType = "";	
		DateTimeFormatter df = null;
		String pattern = "";
		String prompt = "";
		
		// 如果数据类型不匹配，为了定位具体属性名，逐个检查
		for(String paramName : params.keySet()) {
			if (paramPropMap.containsKey(paramName)) {
				// 如果纳入参数属性映射字典，获取参数字段定义
				pfItem = paramPropMap.get(paramName);
				String propName = pfItem.getPropName();
				String addInfo = pfItem.getAddInfo();
				try {
		    		Field field = clazz.getDeclaredField(propName);
		    		field.setAccessible(true);	
					// 获取字段类型
					type = field.getType().getTypeName();
					shortType = getShortTypeName(type);
		    		
					// 获取默认值
					Object oDefaultVal = field.get(item);
					// 获取参数值
					Object paramVal = params.get(paramName);
					// null值匹配检查
					if (paramVal == null) {
						// 如果参数值为null
						if (oDefaultVal != null) {
							// 属性字段不能为null
							throw new BaseException(ExceptionCodes.ARGUMENTS_ERROR,paramName + " should not be null");
						}else {
							// 都为null，忽略后续检查
							continue;
						}
					}
					if (shortType.equals("Object")) {
						// 对象类，参数可以是任意值
						continue;
					}
					
					// 数据类型检查
					if (!addInfo.equals("list")) {
						// 非列表字段
						switch(shortType) {
						case "Integer":
						case "int":
						case "Byte":
						case "byte":
						{
							prompt = shortType;
							Integer iVal = Integer.valueOf(paramVal.toString());
						}
							break;
						case "Long":
						case "long":
						{
							prompt = shortType;
							Long lVal = Long.valueOf(paramVal.toString());
						}
							break;
						case "String":
						{
							prompt = shortType;							
							String sVal = (String)paramVal;	
						}
							break;
						case "LocalDateTime":
						{
							// 默认格式化串
							pattern = "yyyy-MM-dd HH:mm:ss";
							if (!addInfo.isEmpty()) {
								pattern = addInfo;
							}
							prompt = shortType + ":" + pattern;							
							df = DateTimeFormatter.ofPattern(pattern);
							LocalDateTime ldtVal = LocalDateTime.parse((String)paramVal,df);
						}
							break;
						case "LocalDate":
						{
							pattern = "yyyy-MM-dd";
							if (!addInfo.isEmpty()) {
								pattern = addInfo;
							}
							prompt = shortType + ":" + pattern;							
							df = DateTimeFormatter.ofPattern(pattern);
							LocalDate ldVal = LocalDate.parse((String)paramVal,df);							
						}
							break;
						case "LocalTime":
						{
							pattern = "HH:mm:ss";
							if (!addInfo.isEmpty()) {
								pattern = addInfo;
							}
							prompt = shortType + ":" + pattern;							
							df = DateTimeFormatter.ofPattern(pattern);
							LocalTime ldtVal = LocalTime.parse((String)paramVal,df);							
						}
							break;
						default:
							// 暂时忽略其它类型
							break;
						}
						
					}else {
						// 列表字段
						// 针对常见数据类型进行检查
						switch(shortType) {
						case "Integer":
						case "int":
						case "Byte":
						case "byte":
						{
							prompt = "List<Integer>";
							List<Integer> itemList = (List<Integer>)paramVal;
							// 必须取一个值，以确定成员的数据类型是否匹配
							if (itemList.size() > 0) {
								Integer item0 = itemList.get(0);
							}
						}
							break;
						case "Long":
						case "long":
						{
							prompt = "List<Long>";
							List<Long> itemList = (List<Long>)paramVal;
							if (itemList.size() > 0) {
								Long item0 = itemList.get(0);
							}							
						}
							break;
						case "String":
						{
							prompt = "List<String>";							
							List<String> itemList = (List<String>)paramVal;
							if (itemList.size() > 0) {
								String item0 = itemList.get(0);
							}							
						}
							break;
						default:
							// 暂时忽略其它类型
							break;
						}
						
					}
					
				}catch(Exception e) {
					throw new BaseException(ExceptionCodes.DATETYPE_WRONG,
							paramName + " : datatype should be " + prompt + ".");						
				}
			}
		}
	}
	
	/**
	 * 
	 * @methodName		: getNormalFiledNames
	 * @description	: 获取对象的普通数据类型字段名列表
	 * @param <T>		: 泛型类型
	 * @param item		: T类型对象
	 * @return			: 普通数据类型字段名列表
	 * @history		:
	 * ------------------------------------------------------------------------------
	 * date			version		modifier		remarks                   
	 * ------------------------------------------------------------------------------
	 * 2023/03/26	1.0.0		sheng.zheng		初版
	 *
	 */
	public static <T> List<String> getNormalFiledNames(T item){
		List<String> fieldNameList = new ArrayList<String>();
		// 获取对象item的运行时的类
		Class<?> clazz = (Class<?>) item.getClass();
		// 获取属性字段数组
		Field[] fields = clazz.getDeclaredFields();
		String type = "";
		String shortType = "";	
		
		// 遍历所有属性字段
		for (int i = 0; i < fields.length; i++) {
			Field field = fields[i];
			String fieldName = field.getName();
			try {
				// 将私有属性改为可访问
				field.setAccessible(true);
				// 获取字段类型
				type = field.getType().getTypeName();
				shortType = getShortTypeName(type);
				switch(shortType) {
				case "Integer":
				case "int":
				case "Byte":
				case "byte":
				case "Long":
				case "long":
				case "String":
				case "LocalDateTime":
				case "LocalDate":
				case "LocalTime":
					fieldNameList.add(fieldName);
					break;
				default:
					// 忽略其它数据类型
					break;				
				}
			}catch(Exception e) {
	    		continue;
	    	}
		}
		return fieldNameList;		
	}	
	
	/**
	 * 
	 * @methodName		: checkMandatoryFields
	 * @description	: 检查必选字段，与对象的默认值比较，如不同，则表示有值
	 * @param <T>		: 泛型类型，实体对象类
	 * @param item		: 实体对象
	 * @param mandatoryFields: 必选属性名数组
	 * @param escapeFields	: 默认值为有效的属性名数组
	 * @history		:
	 * ------------------------------------------------------------------------------
	 * date			version		modifier		remarks                   
	 * ------------------------------------------------------------------------------
	 * 2024/01/18	1.0.0		sheng.zheng		初版
	 *
	 */
	@SuppressWarnings("unchecked")
	public static <T> void checkMandatoryFields(T item,String[] mandatoryFields,
			String[] escapeFields) {
		Class<T> clazz = (Class<T>) item.getClass();
		// 通过反射创建泛型T的实例，目的是为了获取属性的默认值
		T defItem = null;
		try {
			defItem = clazz.newInstance();
		}catch (Exception e){
			throw new BaseException(ExceptionCodes.ERROR,e.getMessage());
		}

		String error = "";
		for(String propName : mandatoryFields) {
			try {
	    		Field field = clazz.getDeclaredField(propName);
	    		field.setAccessible(true);		    		
				// 获取属性值
				Object oVal = field.get(item);
	    		field.setAccessible(true);		    		
				// 获取属性默认值
				Object oVal2 = field.get(defItem);
				if (oVal != null) {
					// 新值不为null
					if (oVal2 != null) {
						// 默认值不为null
						if (oVal.equals(oVal2)) {
							// 如果新增为默认值
							boolean bEscape = false;
							for(String escape : escapeFields) {
								if (propName.equals(escape)) {
									bEscape = true;
									break;
								}
							}
							if (!bEscape) {
								// 如果此字段不能忽略，则表示必选字段未填值
								if (error.isEmpty()) {
									error += propName;								
								}else {
									error += "," + propName;
								}
							}
						}
					}
				}else {
					// 新值为null
					error += propName + ",";
					continue;					
				}
			}catch(Exception e) {
				// 非属性字段
				if (error.isEmpty()) {
					error += propName;											
				}else {
					error += "," + propName;
				}
			}			
		}
		if (!error.isEmpty()) {
			throw new BaseException(ExceptionCodes.ARGUMENTS_IS_EMPTY,error);
		}		
	}
	
	/**
	 * 
	 * @methodName		: checkMandatoryFields
	 * @description	: 检查必选字段，与对象的默认值比较，如不同，则表示有值
	 * @summary			: 此方法用于检查对象列表，默认值对象由外部创建一次
	 * @param <T>		: 泛型类型，实体对象类
	 * @param item		: 实体对象
	 * @param defItem	: 实体对象，对象属性使用默认值
	 * @param mandatoryFields: 必选属性名数组
	 * @param escapeMap	: 默认值为有效的属性名字典，key为属性名，value为1
	 * @return			: 异常信息，空串表示无异常
	 * @history		:
	 * ------------------------------------------------------------------------------
	 * date			version		modifier		remarks                   
	 * ------------------------------------------------------------------------------
	 * 2024/01/18	1.0.0		sheng.zheng		初版
	 *
	 */
	public static <T> String checkMandatoryFields(T item,T defItem, String[] mandatoryFields,
			Map<String,Integer> escapeMap) {
		Class<?> clazz = (Class<?>) item.getClass();
		String error = "";
		for(String propName : mandatoryFields) {
			try {
	    		Field field = clazz.getDeclaredField(propName);
	    		field.setAccessible(true);		    		
				// 获取属性值
				Object oVal = field.get(item);
	    		field.setAccessible(true);		    		
				// 获取属性默认值
				Object oVal2 = field.get(defItem);
				if (oVal != null) {
					// 新值不为null
					if (oVal2 != null) {
						// 默认值不为null
						if (oVal.equals(oVal2)) {
							// 如果新增为默认值
							if(escapeMap.containsKey(propName)) {
								// 如果默认值有效，则忽略
								continue;
							}
							if (error.isEmpty()) {
								error += propName;								
							}else {
								error += "," + propName;
							}
						}
					}
				}else {
					// 新值为null
					error += propName + ",";
					continue;					
				}
			}catch(Exception e) {
				// 非属性字段
				if (error.isEmpty()) {
					error += propName;											
				}else {
					error += "," + propName;
				}
			}			
		}
		if (!error.isEmpty()) {
			error = item.toString() + ": " + error;
		}
		return error;
	}	
}
